Alternatif Jawaban: Permasalahan Pemenuhan ATK Office

Workshop Melek Data

Author

Departemen Market Research - Nutrifood Indonesia

Published

January 16, 2024

Pendahuluan

Latar Belakang

Salah satu tugas dari tim office adalah supporting another department dalam hal kebutuhan sarana dan prasarana kerja, termasuk ke dalam pemenuhan kebutuhan alat tulis kantor. Setiap harinya, user di masing-masing departemen bisa melakukan request alat tulis kantor menggunakan sistem IT yang ada. Setiap request tersebut dicatat secara otomatis. Setelah itu, tim office wajib memenuhi request tersebut dan menuliskan rekap pemberian (serah terima) tersebut secara harian.

Data-data ini disimpan secara rapi namun belum pernah terutilisasi lebih lanjut.

Data yang Dimiliki

Pada folder ini kalian akan menemukan dua buah files berformat .xlsx, yakni:

Data I: dbase pengeluaran produk.xlsx

dbase pengeluaran produk.xlsx, yakni transaksi harian pemberian produk alat tulis kantor yang dilakukan tim office kepada orang yang meminta (request) di masing-masing departemen. Berikut adalah sampel dari data yang ada:

Code
df = read_excel("~/melek-data/Problems/ATK/dbase pengeluaran produk.xlsx")
df[1:10,] |> knitr::kable()
tanggal nama_item kode_item jml_keluar satuan pemohon_nama pemohon_dept
2022-07-25 KERTAS A4 80GR ATKYHO085 3 RIM Delgado, Sierra LAA
2022-02-02 Materai 10000 ATKYHO164 50 pcs Delgado, Sierra LAA
2021-06-14 Materai 10000 ATKYHO164 20 pcs Delgado, Sierra LAA
2022-06-28 POCKET BANTEX 2044 ATKYHO127 2 PACK Delgado, Sierra LAA
2023-08-02 BALLPOINT HITAM ATKYHO010 3 PCS Delgado, Sierra LAA
2023-05-26 KERTAS F4 80GR PAPERONE ATKYHO089 1 RIM Delgado, Sierra LAA
2022-04-11 Materai 10000 ATKYHO164 100 pcs Delgado, Sierra LAA
2021-12-08 Materai 10000 ATKYHO164 100 pcs Delgado, Sierra LAA
2022-08-04 KERTAS KOP SURAT NUTRIFOOD A4 STOKYHO199 5 RIM Delgado, Sierra LAA
2022-05-18 BALLPOINT HITAM ATKYHO010 2 PCS Delgado, Sierra LAA

Struktur datanya sebagai berikut:

Code
str(df)
tibble [2,697 × 7] (S3: tbl_df/tbl/data.frame)
 $ tanggal     : POSIXct[1:2697], format: "2022-07-25" "2022-02-02" ...
 $ nama_item   : chr [1:2697] "KERTAS A4 80GR" "Materai 10000" "Materai 10000" "POCKET BANTEX 2044" ...
 $ kode_item   : chr [1:2697] "ATKYHO085" "ATKYHO164" "ATKYHO164" "ATKYHO127" ...
 $ jml_keluar  : num [1:2697] 3 50 20 2 3 1 100 100 5 2 ...
 $ satuan      : chr [1:2697] "RIM" "pcs" "pcs" "PACK" ...
 $ pemohon_nama: chr [1:2697] "Delgado, Sierra" "Delgado, Sierra" "Delgado, Sierra" "Delgado, Sierra" ...
 $ pemohon_dept: chr [1:2697] "LAA" "LAA" "LAA" "LAA" ...

Data II: dbase pembelian produk.xlsx

dbase pembelian produk.xlsx, yakni transaksi harian pembelian produk alat tulis kantor yang dilakukan tim office kepada supplier. Berikut adalah sampel datanya:

Code
df = read_excel("~/melek-data/Problems/ATK/dbase pembelian produk.xlsx")
df[1:10,] |> knitr::kable()
tanggal nama_item kode_item jml_masuk satuan nomor_po dibeli_dari harga_beli total_beli
2021-01-18 CONTINUOUS FORM FAKTUR BISNIS 9.5”X11”,2 PLY STOKYHO063 14 BOX 160165 Citra Satriawidya Andhika, PT 285000 3990000
2021-01-18 MATERAI 3000 ATKYHO106 2000 PCS 161914 POS INDONESIA, PT 3000 6000000
2021-01-15 AMPLOP COKLAT A3 ATKYHO002 10 PACK 161729 ARTHA STATIONERY, CV 75000 750000
2021-01-18 AMPLOP PUTIH POLOS NO. 90 ATKYHO006 10 PACK 161731 SIGMA BERKAT SEJATI, PT 16250 162500
2021-01-18 BALLPOINT HITAM ATKYHO010 60 PCS 161731 SIGMA BERKAT SEJATI, PT 2100 126000
2021-01-15 BINDER CLIP NO.107 ATKYHO020 50 LUSIN 161729 ARTHA STATIONERY, CV 2450 122500
2021-01-18 CELLOTAPE 1/2X10 YDS PANFIX ATKYHO037 60 ROLL 161731 SIGMA BERKAT SEJATI, PT 5250 315000
2021-01-18 COVER BUFFALO ATKYHO057 10 PACK 161731 SIGMA BERKAT SEJATI, PT 33600 336000
2021-01-18 GUNTING KECIL ATKYHO074 5 PCS 161731 SIGMA BERKAT SEJATI, PT 5513 27565
2021-01-18 ISI STAPLES KECIL NO.10 ATKYHO080 100 DUS 161731 SIGMA BERKAT SEJATI, PT 1900 190000

Struktur datanya sebagai berikut:

Code
str(df)
tibble [501 × 9] (S3: tbl_df/tbl/data.frame)
 $ tanggal    : POSIXct[1:501], format: "2021-01-18" "2021-01-18" ...
 $ nama_item  : chr [1:501] "CONTINUOUS FORM FAKTUR BISNIS 9.5\"X11\",2 PLY" "MATERAI 3000" "AMPLOP COKLAT A3" "AMPLOP PUTIH POLOS NO. 90" ...
 $ kode_item  : chr [1:501] "STOKYHO063" "ATKYHO106" "ATKYHO002" "ATKYHO006" ...
 $ jml_masuk  : num [1:501] 14 2000 10 10 60 50 60 10 5 100 ...
 $ satuan     : chr [1:501] "BOX" "PCS" "PACK" "PACK" ...
 $ nomor_po   : chr [1:501] "160165" "161914" "161729" "161731" ...
 $ dibeli_dari: chr [1:501] "Citra Satriawidya Andhika, PT" "POS INDONESIA, PT" "ARTHA STATIONERY, CV" "SIGMA BERKAT SEJATI, PT" ...
 $ harga_beli : chr [1:501] "285000" "3000" "75000" "16250" ...
 $ total_beli : num [1:501] 3990000 6000000 750000 162500 126000 ...

Masalah

Problem Statement

Masalah yang dihadapi oleh tim office adalah:

  • Jika semua produk overstok, maka bisa jadi ada kemungkinan barang terlalu lama “parkir” di gudang dan tidak terpakai.
  • Jika semua produk understok, maka user akan gelisah menunggu kapan request-nya bisa didapatkan.

Oleh karena itu, menggunakan data-data yang ada:

Bantu tim office membuat strategi inbound - outbound (pemenuhan stok) yang optimal!

Buat satu materi presentasi sederhana yang bisa menjelaskan ide dan strategi tim Anda! Silakan gunakan tools pengolahan data sesuai dengan preferensi tim Anda!

Catatan: data ini dirancang untuk bisa diselesaikan cukup dengan Ms. Excel.

Discussion

Apakah ada:

  • Variabel dari data yang tidak digunakan dalam membuat strategi tersebut?
  • Variabel yang belum ada pada data namun diperlukan dalam membuat strategi tersebut? Jika ada, sebutkan dan bahas dalam materi presentasi tim Anda!
  • Asumsi yang tim Anda gunakan dalam membuat strategi tersebut?

Hints

Untuk membantu menyelesaikan masalah ini, Anda bisa mempertimbangkan untuk melakukan beberapa hal berikut ini:

  1. Membuat pre-analisa berupa analisa deskriptif dari kedua data tersebut.
  2. Strategi yang bisa dipertimbangkan: cost efficiency atau service level.
  3. Keep it simple! Seringkali masalah yang terlihat rumit dan kompleks sebenarnya bisa diselesaikan dengan pendekatan sederhana jika kita benar-benar bisa menyesuaikan tujuan dengan metode atau analisa yang digunakan.
  4. Melakukan transformasi kepada data yang memiliki range yang sangat lebar. Transformasi yang bisa dilakukan antara lain:

Scaling dengan formula berikut:

\hat{X} = \frac{X-\bar{X}}{X_{max}-X_{min}}

Standardization dengan formula berikut:

\hat{X} = \frac{X-\bar{X}}{\sigma_X}

Fungsi logaritmik dengan formula berikut:

\hat{X} = \log{X}

Fungsi transformasi Tukey lainnya.

Selamat Mengerjakan!

Notes: Setiap tim diperbolehkan bertanya kepada observer sebanyak tiga kali!


Alternatif Jawaban

Permasalah di atas bisa diselesaikan dengan berbagai macam jawaban. Asumsi yang dipakai juga bisa beragam. Namun, walaupun tidak ada jawaban benar dan salah, kita tetap bisa menguji apakah asumsi yang kita gunakan logis atau tidak.

Pada bagian ini, kami memberikan satu alternatif jawaban yang bisa digunakan.

Tujuan

Tujuan utama dari analisa ini adalah memberikan masukan berupa strategi pemenuhan ATK tim office, yakni bagaimana melakukan inbound dan outbound dari ATK yang ada.

Kunci pemenuhan ATK terletak dari bagaimana tim office membeli dan melakukan proses stocking yang baik. Oleh karena itu, kami tidak menggunakan dataset pembelian ATK. Kami hanya mengambil variabel harga dari masing-masing ATK dari dataset tersebut.

Untuk bisa membeli dengan tepat, kita bisa membagi seluruh ATK menjadi kelompok-kelompok sesuai dengan karakteristiknya. Pada analisa ini, kami membagi ATK sesuai dengan:

  1. Harga dan
  2. Banyaknya request terhadap ATK tersebut pada tahun 2023. Kenapa range waktunya dipersempit?

Kita bisa melakukan beberapa pre-analisa terlebih dahulu.

Pre-Analisa

Data Pembelian ATK

Code
# kita panggil datanya
df_1 = read_excel("~/melek-data/Problems/ATK/dbase pembelian produk.xlsx")

# buat default periodenya
periode_default = c(paste(1:12,2018,sep = "-"),
                    paste(1:12,2019,sep = "-"),
                    paste(1:12,2020,sep = "-"),
                    paste(1:12,2021,sep = "-"),
                    paste(1:12,2022,sep = "-"),
                    paste(1:12,2023,sep = "-"))

# kita enrich dulu untuk perhitungan
df_1 = 
  df_1 |>
  mutate(bulan = lubridate::month(tanggal),
         tahun = lubridate::year(tanggal)) |>
  mutate(periode = paste(bulan,tahun,sep = "-"),
         periode = factor(periode,levels = periode_default))

# plot pertama
df_1 |>
  group_by(periode) |>
  summarise(beli = sum(total_beli)) |>
  ungroup() |>
  mutate(label = beli / 10^6,
         label = round(label,1),
         label = paste0("Rp",label,"jt")) |>
  ggplot(aes(x = periode,
             y = beli)) +
  geom_line(group = 1,color = "steelblue") +
  geom_text(aes(label = label),alpha = .5,size = 1.5) +
  scale_x_discrete(guide = guide_axis(n.dodge=4)) +
  theme_minimal() +
  labs(title = "Trend Pembelian ATK per Bulan",
       subtitle = "Sumber: data pembelian ATK",
       x = "Periode",
       y = "Total Pembelian (Rp)") +
  theme(axis.text.y = element_blank())

Code
# plot tentang harga per jenis satuan barang ATK
df_1 |>
  mutate(satuan = tolower(satuan),
         satuan = trimws(satuan)) |>
  select(satuan,harga_beli) |>
  distinct() |>
  mutate(harga_beli = as.numeric(harga_beli)) |>
  group_by(satuan) |>
  summarise(min = min(harga_beli),
            max = max(harga_beli),
            mean = mean(harga_beli,na.rm = T)) |>
  ungroup() |>
  ggplot() +
  geom_errorbar(aes(x = satuan,ymin = min,ymax = max),
                width = .2) +
  geom_point(aes(x = satuan,y = mean),shape = 4,color = "darkred") +
  labs(title = "Range Harga ATK per Jenis Satuannya") +
  theme_minimal() +
  labs(subtitle = "Sumber: data pembelian ATK",
       x = "Jenis Satuan ATK",
       y = "Range Harga (Rp)")

Dari grafik di atas, kita melihat range harga yang cukup jauh di beberapa jenis satuan. Oleh karena itu, kami melakukan transformasi logaritmik agar range-nya menjadi lebih comparable.

Code
# plot tentang harga per jenis satuan barang ATK
df_1 |>
  mutate(satuan = tolower(satuan),
         satuan = trimws(satuan)) |>
  select(satuan,harga_beli) |>
  distinct() |>
  mutate(harga_beli = as.numeric(harga_beli)) |>
  group_by(satuan) |>
  mutate(harga_beli = log(harga_beli)) |>
  summarise(min = min(harga_beli),
            max = max(harga_beli),
            mean = mean(harga_beli,na.rm = T)) |>
  ungroup() |>
  ggplot() +
  geom_errorbar(aes(x = satuan,ymin = min,ymax = max),
                width = .2) +
  geom_point(aes(x = satuan,y = mean),shape = 4,color = "darkred") +
  labs(title = "Range Log Harga ATK per Jenis Satuannya") +
  theme_minimal() +
  labs(subtitle = "Sumber: data pembelian ATK",
       x = "Jenis Satuan ATK",
       y = "Range Harga (Rp) - logaritmik")

Data Pengeluaran Produk

Code
# import data
df_2 = read_excel("~/melek-data/Problems/ATK/dbase pengeluaran produk.xlsx")

# kita enrich terlebih dahulu sesuai dengan df_1
df_2 = 
  df_2 |>
  mutate(bulan = lubridate::month(tanggal),
         tahun = lubridate::year(tanggal)) |>
  mutate(periode = paste(bulan,tahun,sep = "-"),
         periode = factor(periode,levels = periode_default))

tabel_1 = 
  df_2 |>
  group_by(tahun,nama_item) |>
  summarise(outbound = sum(jml_keluar)) |>
  ungroup() |>
  reshape2::dcast(nama_item ~ tahun,value.var = "outbound") |>
  arrange(desc(`2023`)) |>
  rename("Nama ATK" = nama_item) |>
  head(20) 

tabel_1 |>
  knitr::kable(align = "c",caption = "Total Serah Terima ATK per Tahun (20 ATK Teratas - Diurutkan dari Angka Tahun 2023)")
Total Serah Terima ATK per Tahun (20 ATK Teratas - Diurutkan dari Angka Tahun 2023)
Nama ATK 2021 2022 2023
Materai 10000 1820 3685 3250
KERTAS A4 80GR 1245 1044 1049
BALLPOINT HITAM 264 496 583
ISI STAPLES KECIL NO.10 363 392 364
LAKBAN BENING 2” 2779 237 288
CELLOTAPE 1/2X10 YDS PANFIX 356 282 281
BINDER CLIP NO.107 295 296 266
MAP BENING CLEAR SLEEVE F4 307 255 230
BATERAI SIZE A2 1.5 VOLT ALKALINE 83 146 183
BINDER CLIP NO.155 171 196 145
LEM STICK 25GR KENKO 56 65 81
BATERAI SIZE A3 1.5 VOLT ALKALINE 75 38 77
SPIDOL ARTLINE 70 HITAM 29 59 68
POST IT 3M 654 (7 X 7 CM) NA 35 64
AMPLOP COKLAT NUTRIFOOD 39 50 63
COVER BUFFALO 33 55 60
ISI PENSIL MEKANIK PILOT 38 43 52
FORM SURAT PENGANTAR 69 37 51
PAPER CLIP No. 5 38 29 47
KERTAS A4 70 GR PP LITE 5 13 45
Code
tabel_2 = 
  df_2 |>
  filter(tahun == 2023) |>
  filter(nama_item %in% tabel_1$`Nama ATK`) |>
  group_by(nama_item,bulan) |>
  summarise(outbound = sum(jml_keluar)) |>
  ungroup() |>
  reshape2::dcast(nama_item ~ bulan,value.var = "outbound")
  
tabel_2[is.na(tabel_2)] = 0

tabel_2 |> 
  rename("Nama ATK" = nama_item) |>
  knitr::kable(align = "c",caption = "Total Serah Terima ATK per Bulan (20 ATK Teratas - Diurutkan dari Angka Tahun 2023)")
Total Serah Terima ATK per Bulan (20 ATK Teratas - Diurutkan dari Angka Tahun 2023)
Nama ATK 1 2 3 4 5 6 7 8 9 10 11 12
AMPLOP COKLAT NUTRIFOOD 2 0 2 0 4 19 3 12 5 15 0 1
BALLPOINT HITAM 46 19 58 0 84 96 51 76 35 33 57 28
BATERAI SIZE A2 1.5 VOLT ALKALINE 6 22 30 0 26 18 14 18 10 22 15 2
BATERAI SIZE A3 1.5 VOLT ALKALINE 12 0 2 0 12 30 0 10 2 2 7 0
BINDER CLIP NO.107 10 30 30 0 50 36 20 17 23 15 18 17
BINDER CLIP NO.155 2 29 14 13 12 9 9 17 17 9 14 0
CELLOTAPE 1/2X10 YDS PANFIX 13 44 13 20 27 30 1 41 14 11 36 31
COVER BUFFALO 30 0 0 0 10 0 0 5 15 0 0 0
FORM SURAT PENGANTAR 0 6 0 0 4 11 5 21 0 0 4 0
ISI PENSIL MEKANIK PILOT 4 9 5 2 1 0 10 4 2 4 11 0
ISI STAPLES KECIL NO.10 93 16 49 22 10 23 13 30 9 41 38 20
KERTAS A4 70 GR PP LITE 0 0 7 0 0 10 0 0 11 0 5 12
KERTAS A4 80GR 86 80 85 100 100 85 85 90 75 79 99 85
LAKBAN BENING 2” 13 6 40 45 20 18 6 61 10 48 1 20
LEM STICK 25GR KENKO 0 4 10 0 10 1 14 3 11 19 5 4
MAP BENING CLEAR SLEEVE F4 28 40 42 0 0 2 34 27 15 10 12 20
Materai 10000 360 160 420 100 380 215 490 130 150 235 260 350
PAPER CLIP No. 5 6 2 0 5 3 0 0 5 3 12 10 1
POST IT 3M 654 (7 X 7 CM) 0 3 10 0 5 0 28 5 3 0 10 0
SPIDOL ARTLINE 70 HITAM 4 5 7 13 3 1 12 6 3 2 12 0

Langkah Pengerjaan

Langkah pengerjaan yang kami lakukan adalah:

  1. Melakukan analisa deskriptif.
    • Apa ada variabel yang perlu atau tidak perlu dimasukkan?
    • Melihat time range yang dijadikan basis strategi inbound-outbound ATK.
  2. Melakukan clustering untuk mengelompokkan ATK sesuai dengan kesamaan karakteristiknya.
    • Apakah bisa dibuat strategi berdasarkan kelompok ATK yang dibuat?
    • Apakah ada perhitungan safety stock yang spesifik di setiap cluster tersebut?

Clustering Analysis